package com.molichuxing.gateway.bff.statistics.services.impl;

import com.molichuxing.gateway.bff.statistics.entity.response.StatisticsAssetVo;
import com.molichuxing.gateway.bff.statistics.services.StatisticsExportService;
import com.molichuxing.gateway.utils.ExcelUtil;
import com.molichuxing.services.infrastructure.dto.response.StatisticsAssetDto;
import com.molichuxing.services.infrastructure.service.StatisticsAssetService;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("statisticsExportService")
public class StatisticsExportServiceImpl implements StatisticsExportService {

    private static final Logger logger = LoggerFactory.getLogger(StatisticsExportServiceImpl.class);

    @Resource
    private  StatisticsAssetService statisticsAssetService;


    private final static Integer FONT_SIZE = 14;
    private final static String FONT_NAME = "等线";

    protected static String getLastMonth() {
        LocalDate today = LocalDate.now();
        today = today.minusMonths(1);
        DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM");
        return formatters.format(today);
    }

    @Override
    public XSSFWorkbook buildWorkbook() throws IOException {
        logger.info("获取 - 监控表（截至"+getLastMonth()+"月）");
        XSSFWorkbook workbook = new XSSFWorkbook();

        Map<Integer,Integer> map = getStatMap();
        //第一个sheet
        buildStatSheet(workbook,"监控表（截至"+getLastMonth()+"月）",map);

        Map<Integer, String[][]> propMap = getPropMap();
        List<Integer> propList = getPropList();
        for (Integer index : propList) {
            String[][] sa = propMap.get(index);
            List<StatisticsAssetVo> list = getDataList(index);
            ExcelUtil.buildNomalSheet(workbook, getSheetName(StatEnum.getEnum(index),map), list,  sa[1],  sa[0]);
        }

//        workbook.write(output);
//        workbook.close();
        return workbook;

    }


    public  Map<Integer,Integer> getStatMap(){
        LocalDateTime date = LocalDateTime.now();
        date = date.minusMonths(1);
        Map<Integer, Integer> res = statisticsAssetService.getStatisticsAssetCount(date);
        return res;
    }


    private  List<StatisticsAssetVo> getDataList(Integer index) {
        List<StatisticsAssetVo> result = new ArrayList<>();

        LocalDateTime date = LocalDateTime.now();
        date = date.minusMonths(1);
        List<StatisticsAssetDto> res = statisticsAssetService.getStatisticsAssetList(date);

        int i = 1;
        for (StatisticsAssetDto dto : res) {
            StatisticsAssetVo vo = new StatisticsAssetVo();
            BeanUtils.copyProperties(dto,vo);
            dto.setId(i++);
            result.add(vo);
        }

        return result;
    }

    public static String getSheetName(StatEnum e,Map<Integer,Integer> map){
        switch (e){
            case SSZ:
                return "特殊-诉讼中"+"("+map.get(e.getCode())+")";
            case DSC:
                return "特殊-待收车"+"("+map.get(e.getCode())+")";
            case HTSJZK:
                return "在库-实际在库"+"("+map.get(e.getCode())+")";
            default:
                return getValueByMap(e,map);
        }
    }


    public static String getValueByMap(StatEnum e,Map<Integer,Integer> map){
        return StatEnum.getCodeName(e.getCode())+"("+map.get(e.getCode())+")";
    }

    private static void buildStatSheet(XSSFWorkbook workbook,String sheetName,Map<Integer,Integer> map) {
        XSSFSheet sheet = workbook.createSheet(sheetName);
        //设置sheet基本属性
        sheet.setDefaultColumnWidth(24);
        sheet.autoSizeColumn(1);
        sheet.setDefaultRowHeight((short) 580);

        ExcelUtil.setCell(workbook,sheet,0,0,sheetName,true,18,FONT_NAME,true,0,0,0,3);
        ExcelUtil.setCell(workbook,sheet,1,0,getValueByMap(StatEnum.ZST,map),false,FONT_SIZE,FONT_NAME,true,1,11,0,0);
        ExcelUtil.setCell(workbook,sheet,1,1,getValueByMap(StatEnum.QKMD,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,2,1,getValueByMap(StatEnum.YYCL,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,3,1,getValueByMap(StatEnum.HTCL,map),false,FONT_SIZE,FONT_NAME,true,3,9,1,1);
        ExcelUtil.setCell(workbook,sheet,3,2,getValueByMap(StatEnum.ECYY,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,4,2,getValueByMap(StatEnum.XS,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,5,2,getValueByMap(StatEnum.HTZK,map),false,FONT_SIZE,FONT_NAME,true,5,7,2,2);
        ExcelUtil.setCell(workbook,sheet,5,3,getValueByMap(StatEnum.HTSJZK,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,6,3,getValueByMap(StatEnum.ZTCL,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,7,3,getValueByMap(StatEnum.ZKSSC,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,8,2,getValueByMap(StatEnum.BFC,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,9,2,getValueByMap(StatEnum.DSCL,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,10,1,getValueByMap(StatEnum.YQJTS,map),false,FONT_SIZE,FONT_NAME,true,10,11,1,1);
        ExcelUtil.setCell(workbook,sheet,10,2,getValueByMap(StatEnum.DSC,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,11,2,getValueByMap(StatEnum.SSZ,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,12,0,getValueByMap(StatEnum.PS,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,13,0,getValueByMap(StatEnum.SJZK,map),false,FONT_SIZE,FONT_NAME);
        ExcelUtil.setCell(workbook,sheet,14,0,getValueByMap(StatEnum.GWC,map),false,FONT_SIZE,FONT_NAME);

    }

    public static Map<Integer,String[][]> getPropMap(){
        Map<Integer,String[][]> map = new HashMap<>();
        String [][] ZST = {
                {"序号","车架号","用户姓名","业务类型","车牌号","经销商","下单日期","提车日期","车型","规格"},
                {"id","vin","userName","businessType","licencePlate","dealerName","orderDate","deliveryDate","vehicleModel","specification"}
        };
        String [][] PS = {
                {"序号","车架号","车牌号","库房所在地","车型"},
                {"id","vin","licencePlate","stockName","vehicleModel"}
        };
        String [][] SJZK = {
                {"车架号","车牌号","中转库名称","城市"},
                {"vin","licencePlate","stockName","city"}
        };
        String [][] GWC = {
                {"车架号","车牌号","中转库城市"},
                {"vin","licencePlate","city"}
        };
        String [][] QKMD = {
                {"车架号","用户姓名","车牌号"},
                {"vin","userName","licencePlate"}
        };
        String [][] YYCL = {
                {"车架号","订单号","用户姓名","用户手机号"},
                {"vin","orderCode","userName","userPhone"}
        };
//        String [][] HTCL = {
//                {"序号","车架号","用户姓名","业务类型","车牌号","经销商","下单日期","提车日期","车型","规格"},
//                {"id","vin","userName","businessType","licencePlate","dealerName","orderDate","deliveryDate","vehicleModel","specification"}
//        };
//        map.put(StatEnum.HTCL.getCode(),HTCL);

//        String [][] YQJTS = {
//                {"序号","车架号","用户姓名","业务类型","车牌号","经销商","下单日期","提车日期","车型","规格"},
//                {"id","vin","userName","businessType","licencePlate","dealerName","orderDate","deliveryDate","vehicleModel","specification"}
//        };
//        map.put(StatEnum.YQJTS.getCode(),YQJTS);
        String [][] ECYY = {
                {"车架号","订单号","用户姓名","用户手机号"},
                {"vin","orderCode","userName","userPhone"}
        };
        String [][] XS = {
                {"车架号","售前订单号","售前用户姓名","售前用户手机号"},
                {"vin","orderCode","userName","userPhone"}
        };
//        String [][] HTZK = {
//                {"序号","车架号","用户姓名","业务类型","车牌号","经销商","下单日期","提车日期","车型","规格"},
//                {"id","vin","userName","businessType","licencePlate","dealerName","orderDate","deliveryDate","vehicleModel","specification"}
//        };
//        map.put(StatEnum.HTZK.getCode(),HTZK);
        String [][] BFC = {
                {"车架号","订单号","用户姓名","用户手机号"},
                {"vin","orderCode","userName","userPhone"}
        };
        String [][] DSCL = {
                {"车架号","订单号","用户姓名","用户手机号"},
                {"vin","orderCode","userName","userPhone"}
        };
        String [][] DSC = {
                {"车架号","订单号","用户姓名","用户手机号","状态"},
                {"vin","orderCode","userName","userPhone","carStatus"}
        };
        String [][] SSZ = {
                {"车架号","车牌号","订单号","用户姓名","用户手机号"},
                {"vin","licencePlate","orderCode","userName","userPhone"}
        };
        String [][] HTSJZK = {
                {"车架号","订单号","用户姓名","用户手机号","中转库名称"},
                {"vin","orderCode","userName","userPhone","stockName"}
        };
        String [][] ZTCL = {
                {"车架号","车牌号","订单号"},
                {"vin","licencePlate","orderCode"}
        };
        String [][] ZKSSC = {
                {"车架号","订单号","用户姓名","用户手机号"},
                {"vin","orderCode","userName","userPhone"}
        };

        map.put(StatEnum.ZST.getCode(),ZST); //租售通
        map.put(StatEnum.QKMD.getCode(),QKMD);//全款买断
        map.put(StatEnum.YYCL.getCode(),YYCL);//运营车辆
        map.put(StatEnum.ECYY.getCode(),ECYY);//二次运营
        map.put(StatEnum.XS.getCode(),XS);//销售
        map.put(StatEnum.HTSJZK.getCode(),HTSJZK);//回退-实际在库
        map.put(StatEnum.ZTCL.getCode(),ZTCL);//在途车辆
        map.put(StatEnum.ZKSSC.getCode(),ZKSSC);//在库-诉讼中
        map.put(StatEnum.BFC.getCode(),BFC);//报废车
        map.put(StatEnum.DSCL.getCode(),DSCL);//丢失车
        map.put(StatEnum.DSC.getCode(),DSC);//待收车
        map.put(StatEnum.SSZ.getCode(),SSZ);//诉讼中
        map.put(StatEnum.PS.getCode(),PS);//批售
        map.put(StatEnum.SJZK.getCode(),SJZK);//在库
        map.put(StatEnum.GWC.getCode(),GWC);//公务车
        return map;

    }


    public static List<Integer> getPropList(){
        List<Integer> list = new ArrayList<>();
        list.add(StatEnum.ZST.getCode()); //租售通
        list.add(StatEnum.QKMD.getCode());//全款买断
        list.add(StatEnum.YYCL.getCode());//运营车辆
        list.add(StatEnum.ECYY.getCode());//二次运营
        list.add(StatEnum.XS.getCode());//销售
        list.add(StatEnum.HTSJZK.getCode());//回退-实际在库
        list.add(StatEnum.ZTCL.getCode());//在途车辆
        list.add(StatEnum.ZKSSC.getCode());//在库-诉讼中
        list.add(StatEnum.BFC.getCode());//报废车
        list.add(StatEnum.DSCL.getCode());//丢失车
        list.add(StatEnum.DSC.getCode());//待收车
        list.add(StatEnum.SSZ.getCode());//诉讼中
        list.add(StatEnum.PS.getCode());//批售
        list.add(StatEnum.SJZK.getCode());//在库
        list.add(StatEnum.GWC.getCode());//公务车
        return list;
    }

    public enum StatEnum {

        ZST(1,"租售通"),
        PS(2,"批售"),
        SJZK(3,"在库"),
        GWC(4,"公务车"),
        QKMD(21,"全款买断"),
        YYCL(22,"运营车辆"),
        HTCL(23,"回退车辆"),
        YQJTS(24,"逾期及特殊"),
        ECYY(31,"二次运营"),
        XS(32,"销售"),
        HTZK(33,"在库"),
        BFC(34,"报废车"),
        DSCL(35,"丢失车"),
        DSC(36,"待收车"),
        SSZ(37,"诉讼中"),
        HTSJZK(41,"实际在库"),
        ZTCL(42,"在途车辆"),
        ZKSSC(43,"诉讼中");

        private int code;

        private String cnName;

        private StatEnum(int code, String cnName) {
            this.code = code;
            this.cnName = cnName;
        }

        public int getCode() {
            return code;
        }

        public String getCnName() {
            return cnName;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public void setCnName(String cnName) {
            this.cnName = cnName;
        }
        public static String getCodeName(int code) {
            for (StatEnum e : StatEnum.values()) {
                if (e.code == code) {
                    return e.cnName;
                }
            }
            return null;
        }

        public static StatEnum getEnum(int code) {
            for (StatEnum e : StatEnum.values()) {
                if (e.code == code) {
                    return e;
                }
            }
            return null;
        }
    }
}
